package verification

import (
	"fmt"
	"net/http"
	"reflect"
	"strconv"
	"strings"
)

type verification struct {
}

func NewVerification() *verification {
	return &verification{}
}

//自定义字段验证
func (v *verification) VerificationBind(d interface{}, rep *http.Request) []interface{} {
	////1，获取到验证的标签
	re := make(map[string]interface{})
	var error []interface{}

	// 获取结构体实例的反射类型对象
	tag, _ := v.GetStructWithTag(d)
	for key, val := range tag {
		arr := strings.Split(val.(string), ",")
		re[key] = rep.FormValue(key)
		rule := arr[0][5:] //代表规则
		msg := arr[1][4:]  //代表描述
		split_rule := strings.Split(rule, "|")
		split_msg := strings.Split(msg, "|")
		if len(split_rule) < len(split_msg) {
			panic("验证规则有误，请检查！！！")
		}
		//2，验证含有验证的标签

		//2.2 系统自带的验证
		for kr, sr := range split_rule {
			var str string

			if kr > len(split_msg)-1 {
				str = ""
			} else {
				str = split_msg[kr]
			}
			switch sr {
			case "required":
				basic := v.BasicRequired(key, re[key], str)
				error = append(error, basic)
			case "number":
				number := v.BasicNumber(key, re[key], str)
				error = append(error, number)
			default:
				ref := reflect.ValueOf(d)
				parameter := make([]reflect.Value, 2)
				parameter[0] = reflect.ValueOf(key)
				parameter[1] = reflect.ValueOf(re[key])
				method := ref.MethodByName("Custom")
				call := method.Call(parameter)[0]
				error = append(error, call)
			}
		}
	}
	//3，返回验证的结果
	return error

}

//定义基础验证规则
func (v *verification) BasicRequired(str string, param interface{}, msg string) (message string) {
	par := fmt.Sprintf("%v", param)
	if par == "" && msg == "" {
		message = fmt.Sprintf("%s can not be empty", str)
	}
	if par == "" && msg != "" {
		message = msg
	}
	return message
}

//判断当前的类型是否为数字
func (v *verification) BasicNumber(str string, param interface{}, msg string) (message string) {
	par := fmt.Sprintf("%v", param)
	_, err := strconv.ParseFloat(par, 64)
	if err != nil && msg == "" {
		message = fmt.Sprintf("%s It has to be a number", str)
	}
	if err != nil && msg != "" {
		message = msg
	}
	return message
}

//获取到结构体tag
func (v *verification) GetStructWithTag(d interface{}) (details map[string]interface{}, err error) {
	details = make(map[string]interface{})
	typeOfCat := reflect.TypeOf(d)
	// 遍历结构体所有成员
	for i := 0; i < typeOfCat.NumField(); i++ {
		// 获取每个成员的结构体字段类型
		fieldType := typeOfCat.Field(i)
		// 输出成员名和tag
		tag := fieldType.Tag
		//if tag.Get("form") != " " {
		//	panic(fmt.Sprintf("%s未设置标签form", fieldType.Name))
		//}
		details[tag.Get("form")] = tag.Get("ver")
	}
	return details, nil

}
